﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace LiveUpdate
{
    public partial class frmUpdate : Form
    {
        private IniFile mIniFile;
        private delegate void OutPutMsgDelegate(string msg);
        private delegate void OnClose();

        private Thread th = null;
        private FtpInfo _ftpInfo;
        public FtpInfo FtpInfo
        {
            get { return _ftpInfo; }
            set { _ftpInfo = value; }
        }
        private string _callbackEXE;
        public string CallBackEXE
        {
            get { return _callbackEXE; }
            set { _callbackEXE = value; }
        }
        private FTPClient _ftpClient;

        static readonly string LogFileName = "updlog.txt";
        private bool _isFinishUpdate = false;

        public frmUpdate()
        {
            InitializeComponent();

        }


        private void btnViewLog_Click(object sender, EventArgs e)
        {
            if (File.Exists(LogFileName))
                Process.Start("notepad.exe", Environment.CurrentDirectory + "\\" + LogFileName);
            else
                MessageBox.Show("未找到日志文件！");
        }

        /// <summary>
        /// 延时一段时间后关闭
        /// </summary>
        /// <param name="delay"></param>
        private void CloseWindowDelay(int delay)
        {
            Thread th = new Thread(new ThreadStart(delegate()
            {
                Thread.Sleep(delay);
                _isFinishUpdate = true;
                //try
                //{
                Application.Exit();
                //}
                //catch { }
            }));
            th.Start();
        }


        /// <summary>
        /// 开始更新
        /// </summary>
        private void BeginUpdate()
        {
            OutPutMsgAndWriteLog("正在连接更新服务器并下载程序......");
            _ftpClient = new FTPClient(_ftpInfo);

            try
            {
                _ftpClient.Connect();
            }
            catch (Exception ex)
            {
                OutPutMsgAndWriteLog("连接FTP服务器失败！错误信息：" + ex.Message);
                this.Invoke(new OutPutMsgDelegate(this.OutPutMsg), "更新程序将在10秒钟后自动关闭。");
                _isFinishUpdate = true;
                //Thread.Sleep(3000);
                //this.Invoke(new OnClose(DoClose));//子线程中关闭主线程创建的对象
                CloseWindowDelay(10000);
                return;
            }


            if (!_ftpClient.Connected)
            {
                OutPutMsgAndWriteLog("连接更新服务器失败。");
                this.Invoke(new OutPutMsgDelegate(this.OutPutMsg), "更新程序将在10秒钟后自动关闭。");
                _isFinishUpdate = true;
                //Thread.Sleep(3000);
                //this.Invoke(new OnClose(DoClose));//子线程中关闭主线程创建的对象
                CloseWindowDelay(10000);
                return;
            }

            if (Directory.Exists("updatetemp")) //创建更新缓存文件夹
                Directory.Delete("updatetemp", true);
            Directory.CreateDirectory("updatetemp");

            bool DownLoadError = false;
            bool DownOneError = false;
            string sSoftwareName = "";
            int iLocalSoftVersion = 0;
            int iBBH = 0;
            mIniFile = new IniFile(Application.StartupPath + "\\update.ini");
            mIniFile.WriteString("Software", "SelfUpdated", "0");
            //DataTable dtUpdateSoft = GetUpdateVersionList().Tables[0];

            DataTable dtUpdateSoft =  P_Version.GetUpdateVersionList().Tables[0];
            for (int i = 0; i < dtUpdateSoft.Rows.Count; i++)
            {
                sSoftwareName = dtUpdateSoft.Rows[i]["MC"].ToString();
                iBBH = int.Parse(dtUpdateSoft.Rows[i]["BBH"].ToString());
                iLocalSoftVersion = mIniFile.ReadInt("Software", sSoftwareName, 0);
                if ((iBBH > iLocalSoftVersion) && (sSoftwareName != ""))
                {
                    DownOneError = false;
                    try
                    {
                        OutPutMsgAndWriteLog("正在下载更新文件：" + sSoftwareName);
                        string sSoftwareDir = dtUpdateSoft.Rows[i]["LJ"].ToString();
                        string sCurExecuteFileName = System.IO.Path.GetFileName(Application.ExecutablePath);
                        _ftpClient.Download(sSoftwareDir + "\\" + sSoftwareName, "updatetemp\\");
                        //if (sSoftwareName.ToUpper() == sCurExecuteFileName.ToUpper())
                        //{
                        //    //_ftpClient.ChangeDir(_ftpInfo.RemotePath);
                        //    _ftpClient.Download(sSoftwareDir + "\\" + sSoftwareName, "updatetemp\\");
                        //    //_ftpClient.Download(sSoftwareDir + "\\" + sSoftwareName, Application.StartupPath, "$$$" + sSoftwareName + ".$$$");
                        //    mIniFile.WriteString("Software", "SelfUpdated", "1");
                        //}
                        //else
                        //{
                        //    _ftpClient.Download(sSoftwareDir + "\\" + sSoftwareName, Application.StartupPath);
                        //}
                        //OutPutMsgAndWriteLog( sSoftwareName + "下载成功");
                    }
                    catch (Exception ex)
                    {
                        OutPutMsgAndWriteLog(string.Format("下载更新文件 {0} 失败。错误信息：{1}", sSoftwareName, ex.Message));
                        DownOneError = true;
                        DownLoadError = true;
                    }
                    if (!DownOneError)
                    {
                        mIniFile.WriteInt("Software", sSoftwareName, iBBH);
                    }
                }
            }
            _isFinishUpdate = true;
            OutPutMsgAndWriteLog("程序更新完毕,更新程序将自动关闭");
            //Thread.Sleep(3000);
            //this.Invoke(new OnClose(DoClose));//子线程中关闭主线程创建的对象

            DirectoryInfo tempdir = new DirectoryInfo("updatetemp\\");
            DirectoryInfo[] childDirs = tempdir.GetDirectories();
            foreach (DirectoryInfo childDir in childDirs)
            {
                UpdateFormalDir(childDir, "");
            }
            FileInfo[] files = tempdir.GetFiles();
            foreach (FileInfo file in files)
            {
                OutPutMsgAndWriteLog("更新文件 " + file.Name);
                try
                {
                    file.CopyTo(file.Name, true);
                }
                catch (Exception recoverEx)
                {
                    OutPutMsgAndWriteLog("出现异常：" + recoverEx.Message + "。程序将在10秒钟后自动关闭。");
                    _isFinishUpdate = true;
                    CloseWindowDelay(10000);
                    return;
                }
            }
            tempdir.Delete(true);
            OutPutMsgAndWriteLog("更新完毕。");

            _isFinishUpdate = true;
            Process.Start(_callbackEXE);
            Application.Exit();
        }


        private void StartCallBackEXE()
        {
            Process.Start(_callbackEXE);
            Application.Exit();
        }
        /// <summary>
        /// 从缓存目录更新到正式程序文件夹
        /// </summary>
        /// <param name="fromDir"></param>
        /// <param name="toPath"></param>
        private void UpdateFormalDir(DirectoryInfo fromDir, string toPath)
        {
            string toDir = toPath + fromDir.Name;

            if (!Directory.Exists(toPath + fromDir.Name))
                Directory.CreateDirectory(toPath + fromDir.Name);

            FileInfo[] files = fromDir.GetFiles();
            foreach (FileInfo file in files)
            {
                OutPutMsgAndWriteLog("更新文件 " + toDir + "\\" + file.Name);
                file.CopyTo(toDir + "\\" + file.Name, true);
            }

            DirectoryInfo[] dirs = fromDir.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                UpdateFormalDir(dir, toDir + "\\");
            }
        }


        private void DoClose()
        {
            Close();
        }

        private void OutPutMsgAndWriteLog(string msg)
        {
            this.Invoke(new OutPutMsgDelegate(this.OutPutMsg), msg);

            File.AppendAllText(LogFileName, msg.Replace("\r\n", ""), Encoding.GetEncoding("gb2312"));
            File.AppendAllText(LogFileName, DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss"));
            File.AppendAllText(LogFileName, "\r\n");
        }
        private void OutPutMsg(string msg)
        {
            rtxtMsg.AppendText(msg);
            rtxtMsg.AppendText("\r\n");
        }

    


        private void StartUpdateBat()
        {
            string sBatFile = "update.bat";
            string TmpFile = "";
            string NowFile = "";

            string sCurExecuteFileName = System.IO.Path.GetFileName(Application.ExecutablePath);
            if (File.Exists("$$$" + sCurExecuteFileName + ".$$$"))
            {
                TmpFile = "$$$" + sCurExecuteFileName + ".$$$";
                NowFile = sCurExecuteFileName;

            }
            StreamWriter sw = new StreamWriter(sBatFile);
            sw.WriteLine("@echo off");
            //sw.WriteLine(":loop");
            //sw.WriteLine("if exist .\\" + TmpFile + " del .\\" + NowFile);
            //sw.WriteLine("if exist .\\" + TmpFile + " if exist .\\" + NowFile + " goto loop");
            //sw.WriteLine("copy .\\" + TmpFile + "  .\\" + NowFile);
            //sw.WriteLine("del .\\" + TmpFile);
            //IniFile mIniFile = new IniFile(Application.StartupPath + "\\update.ini");
            //string sSelfUpdated = mIniFile.ReadString("Software", "SelfUpdated", "1");
            //if (sSelfUpdated == "1")
            //{
            //    sw.WriteLine("start " + NowFile);
            //}
            //sw.WriteLine("CLS");
            //sw.WriteLine("del .\\" + sBatFile);
            sw.WriteLine("copy .\\updatetemp\\* .\\");
            sw.WriteLine("start " + NowFile);
            sw.WriteLine("del .\\" + sBatFile);
            sw.Flush();
            sw.Close();
            if (File.Exists(sBatFile))
            {
                // Process.Start(sBatFile);
                Process proc = new Process();
                proc.StartInfo.FileName = sBatFile;
                //proc.StartInfo.Arguments = prg;
                //proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.StartInfo.ErrorDialog = false;

                //proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(Application.StartupPath);
                proc.Start();
                proc.WaitForExit();
            }
            Environment.Exit(0);
        }

        private void frmUpdate_Shown(object sender, EventArgs e)
        {

            _ftpInfo = new FtpInfo("127.0.0.1", "\\", "brs", "brs", 21);
            _callbackEXE = @"E:\CrissCross\NJ2H\source\Lib\CodePortal.exe";
            OutPutMsgAndWriteLog("---------------------------------------------------------------------------");

            if (string.IsNullOrEmpty(_ftpInfo.RemoteHost))
            {
                rtxtMsg.AppendText("自动更新失败！错误信息：参数未设置。");
                rtxtMsg.AppendText("程序将在10秒钟后自动关闭......");
                _isFinishUpdate = true;
                Thread.Sleep(10000);
            }
            else
            {
                th = new Thread(delegate()
                {
                    BeginUpdate();
                });
                th.IsBackground = true;
                th.Start();
                //BeginUpdate();
            }
        }

        private void frmUpdate_FormClosed(object sender, FormClosedEventArgs e)
        {
            //StartUpdateBat();

            //IniFile mIniFile = new IniFile(Application.StartupPath + "\\update.ini");
            //string sSelfUpdated = mIniFile.ReadString("Software", "SelfUpdated", "1");
            //if (sSelfUpdated == "1")
            //{
            //    MessageBox.Show("主程序已做更新,系统将重新登录");
            //    StartUpdateBat();
            //}
        }
    }
}
